﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

using Jzy.Workflow.Flow;
using Jzy.Workflow.Task;
using Jzy.Workflow.Node;
using System.Text;

using Jzy.Workflow.Snap;
using System.Xml.Linq;
using Jzy.Workflow.Line;
using Jzy.Workflow.Line.Rules;
using Frame.Lib.Core.User;
using Frame.Lib.Common;
using Frame.Lib.Utilities;


namespace Jzy.Web.WorkFlow.Fore
{
    public partial class Send : PageEdit
    {
        //接收下一节点接收人的hidden
        public string hidSendID
        {
            get
            {
                return Request.QueryString["hidSend"];
            }
        }
        public string hidAddSignID
        {
            get
            {
                return Request.QueryString["hidAddSign"];
            }
        }
        public string hidPassRoundID
        {
            get
            {
                return Request.QueryString["hidPassRound"];
            }
        }
        public string hidNextNodeID
        {
            get
            {
                return Request.QueryString["hidNextNode"];
            }
        }

        public string btnTransferID
        {
            get
            {
                return Request.QueryString["btnTransfer"];
            }
        }

        public string FlowID
        {
            get
            {
                return Request.QueryString["FlowID"];
            }
        }
        public string TaskID
        {
            get
            {
                return Request.QueryString["TaskID"];
            }
        }



        protected void Page_Load(object sender, EventArgs e)
        {
            if (!IsPostBack)
            {
                InitData();
            }
            AddAttr();
        }

        private void AddAttr()
        {
            lstNode.Attributes.Add("onchange", "node_click(this,'" + hidSend.ClientID + "','" + txtSend.ClientID + "')");

            txtSend.Attributes.Add("readonly", "readonly");

            if (string.IsNullOrEmpty(TaskID))
            {
                btnSelSend.Attributes.Add("onclick", "send_click('" + lstNode.ClientID + "',null," + hidSend.ClientID + "," + txtSend.ClientID + ")");
            }
            else
            {
                btnSelSend.Attributes.Add("onclick", "send_click('" + lstNode.ClientID + "','" + TaskID + "'," + hidSend.ClientID + "," + txtSend.ClientID + ")");
            }
            JSUtil.ShowDeptUserTreeDlg(hidAddSign, txtAddSign, false,false,btnSelAdd);
            JSUtil.ShowDeptUserTreeDlg(hidPassRound, txtPassRound, false,false,btnSelPass);
            //JSUtil.ShowDlg(hidSend, txtSend, "SelectNodeUser.aspx", btnSelSend);
            //JSUtil.ShowDlg
        }

        private void InitData()
        {
            FlowNodeInfo currentNode = null;//当前审核所处节点

            //判断下一节点接收人是不是唯一
            if (string.IsNullOrEmpty(TaskID))//新建表单
            {
                FlowBO flow = new FlowBO();
                FlowInfo flowInfo = flow.GetInfo(FlowID);
                currentNode = flowInfo.StartNode;                
            }
            else //修改表单（暂存的） 或 审核表单  ,如果是被传阅者或加签者就没有下一节点了
            {
                FlowTaskBO task = new FlowTaskBO();
                FlowTaskInfo taskInfo = task.GetInfo(TaskID);
                currentNode = taskInfo.ReceiveNodeInfo;
               
            }
            
            List<FlowNodeInfo> nextNodes = GetNextNodes(currentNode);//下面节点发送节点的集合
            
            if (nextNodes.Count == 0)
            {
                string script = "alert('没有可流转的下一节点，请联系管理员');top.delDivFrm()";
                JSUtil.ResponseJS(script);
            }

            foreach (FlowNodeInfo node in nextNodes)
            {
                lstNode.Items.Add(new ListItem(node.Name, node.ID.ToString()));
            }

            lstNode.SelectedIndex = 0;


            int nextNodeCount = nextNodes.Count;//下一节点数,不可能为0，最后一个是系统结束结点
            if (nextNodeCount == 1)//下一节点唯一
            {
                lblNode.Visible = true;
                lblNode.Text = nextNodes[0].Name;

                lstNode.Style.Add("display", "none");

                if (nextNodes[0].TypeID == (int)FlowNodeType.结束)//结束节点
                {
                    txtSend.Enabled = false;
                    btnSelSend.Attributes.Add("disabled", "disabled");
                    txtAddSign.Enabled = false;
                    btnSelAdd.Attributes.Add("disabled", "disabled");
                    txtPassRound.Enabled = false;
                    btnSelPass.Attributes.Add("disabled", "disabled");
                    RequiredFieldValidator1.Enabled = false;
                }
            }
            else
            {
                lblNode.Visible = false;
                lstNode.Visible = true;
            }

            UserBO user = new UserBO();

            //给处理人加上默认值
            if (nextNodes[0].DefaultUserID != null)
            {
                hidSend.Value = nextNodes[0].DefaultUserID.ToString();
                txtSend.Text = (new UserBO()).GetName(hidSend.Value);
            }
            else
            {
                if (nextNodes[0].IsParallel)//是否是并行提交
                {
                    hidSend.Value = StrUtil.MergeToStr(nextNodes[0].AllUserIDs, ",");
                    txtSend.Text = StrUtil.MergeToStr(user.GetName(nextNodes[0].AllUserIDs), ",");
                }
                else
                {
                    if (nextNodes[0].AllUserIDs.Count > 0)
                    {
                        hidSend.Value = nextNodes[0].AllUserIDs[0].ToString();
                        txtSend.Text = user.GetName(hidSend.Value);
                    }
                }
            }



            //把下一节点的信息以JSON展示到客户端
            StringBuilder json = new StringBuilder();
            foreach (FlowNodeInfo node in nextNodes)
            {
                json.Append(",{ID:'" + node.ID + "',IsParallel:" + node.IsParallel.ToString().ToLower() + ",");
                string userids = "", usernames = "";
                if (node.DefaultUserID != null)//是否有默认用户
                {
                    userids = node.DefaultUserID.ToString();
                    usernames = user.GetName((int)node.DefaultUserID);
                }
                else
                {
                    if (node.IsParallel)//是否允许并行提交
                    {
                        userids = StrUtil.MergeToStr(node.AllUserIDs, ",");
                        usernames = StrUtil.MergeToStr(user.GetName(node.AllUserIDs), ",");
                    }
                    else
                    {
                        if (node.AllUserIDs.Count > 0)
                        {
                            userids = node.AllUserIDs[0].ToString();
                            usernames = user.GetName(node.AllUserIDs[0]);
                        }
                    }

                }
                json.Append("User:{IDs:'" + userids + "',Names:'" + usernames + "'}}");
            }

            string script2 = "arrNodes = [" + json.ToString().TrimStart(',') + "];";
            JSUtil.ExcuteJS(script2);        

        }

        /// <summary>
        /// 获取下一面的审批节点，如果下面的审批节点有当前用户则跳过，再把下面满足路由条件的节点列出
        /// </summary>
        /// <param name="currentNode"></param>
        /// <returns></returns>
        private List<FlowNodeInfo> GetNextNodes(FlowNodeInfo currentNode)
        {
            XElement formData = null;
            if (Session["FormData"] != null)
            {
                formData = (XElement)Session["FormData"];
                Session["FormData"] = null;
                //JSUtil.Alert(formData.Elements().Count().ToString());
            }
            else
            {
                string script = "top.alert('Session意外丢失，请重新提交');top.delDivFrm();";
                JSUtil.ResponseJS(script);
            }

            List<int> filterNodeIDs = GetFilterNodeIDs(currentNode.FromLines, formData);

            IEnumerable<FlowNodeInfo> nextNodes = currentNode.NextNodes.Where(T => filterNodeIDs.Contains(T.ID));//满足路由条件的下面节点

            List<FlowNodeInfo> tmpNodes = new List<FlowNodeInfo>();//如果下面节点有当前用户审批的，则把下一节点的下一节点找出来

            //获取当前用户所拥有的角色
            UserBO user = new UserBO();
            List<int> roleIDs = user.GetRoleIDs(AppSession.UserID);

            foreach (FlowNodeInfo info in nextNodes)
            {
                bool isContain = false;//判断此节点用户是否也可以审批，防止自己发送给自己

                if (info.UserIDs.Contains(AppSession.UserID))
                {
                    isContain = true;
                }
                else
                {
                    foreach (int roleID in info.RoleIDs)
                    {
                        if (roleIDs.Contains(roleID))
                        {
                            isContain = true;
                            break;
                        }
                    }
                }

                if (isContain)//该用户可以审核此节点
                {
                    List<int> tmpNodeIDs = GetFilterNodeIDs(info.FromLines, formData);

                    tmpNodes.AddRange(info.NextNodes.Where(T => tmpNodeIDs.Contains(T.ID)));
                }
            }

            tmpNodes.AddRange(nextNodes);//如果在后续节点中用户可以审批，则把后续节点放在最前面

            return tmpNodes;

            
        }

        private List<int> GetFilterNodeIDs(List<FlowLineInfo> lineInfos, XElement formData)
        {
            List<int> nodeIDs = new List<int>();

            UserBO user = new UserBO();
            UserInfo currentUserInfo = user.GetInfo(AppSession.UserID);
            List<int> userRoles = currentUserInfo.RoleIDs;
            List<int> userDepts = currentUserInfo.DeptIDs;

            foreach (FlowLineInfo info in lineInfos)
            {
                if (string.IsNullOrEmpty(info.Rules))//如果没有设定规则，则是可以走的路由
                {
                    nodeIDs.Add(info.ToNodeID);
                }
                else
                {
                    bool flag = true;

                    XElement rules = XElement.Parse(info.Rules);

                    XElement roles = rules.Element("Roles");
                    if (roles.Value != "")
                    {
                        flag = flag && this.Contains(userRoles, StrUtil.SplitToInt(roles.Value));
                    }
                    if (flag)
                    {
                        XElement depts = rules.Element("Depts");
                        if (depts.Value != "")
                        {
                            flag = this.Contains(userDepts, StrUtil.SplitToInt(depts.Value));
                        }
                    }
                    if (flag)
                    {
                        IEnumerable<XElement> fields = rules.Elements("Field");

                        if (fields != null && fields.Count() > 0)
                        {
                            string logic = "";

                            bool flag2 = true; //所有自定义规则逻辑结果

                            #region for循环
                            foreach (XElement field in fields)
                            {
                                string fieldName = field.Element("FieldName").Value;
                                string relation = field.Element("Relation").Value;
                                string compareValue = field.Element("CompareValue").Value;
                                DataType dataType = (DataType)int.Parse(field.Element("DataType").Value);

                                bool flag3 = true;//每一个自定义规则的逻辑结果

                                #region 结果比对
                                if (formData.Element(fieldName) != null)
                                {
                                    string value = formData.Element(fieldName).Value;
                                    switch (relation)
                                    {
                                        case ">":
                                            {
                                                switch (dataType)
                                                {
                                                    case DataType.日期:
                                                        flag3 = DateTime.Parse(value) > DateTime.Parse(compareValue);
                                                        break;
                                                    case DataType.数值:
                                                        flag3 = decimal.Parse(value) > decimal.Parse(compareValue);
                                                        break;
                                                }
                                            }
                                            break;
                                        case ">=":
                                            {
                                                switch (dataType)
                                                {
                                                    case DataType.日期:
                                                        flag3 = DateTime.Parse(value) >= DateTime.Parse(compareValue);
                                                        break;
                                                    case DataType.数值:
                                                        flag3 = decimal.Parse(value) >= decimal.Parse(compareValue);
                                                        break;
                                                }
                                            }
                                            break;
                                        case "==":
                                        case "=":
                                            {
                                                switch (dataType)
                                                {
                                                    case DataType.日期:
                                                        flag3 = DateTime.Parse(value) == DateTime.Parse(compareValue);
                                                        break;
                                                    case DataType.数值:
                                                        flag3 = decimal.Parse(value) == decimal.Parse(compareValue);
                                                        break;
                                                    case DataType.文本:
                                                        flag3 = value == compareValue;
                                                        break;
                                                }
                                            }
                                            break;
                                        case "<":
                                            {
                                                switch (dataType)
                                                {
                                                    case DataType.日期:
                                                        flag3 = DateTime.Parse(value) < DateTime.Parse(compareValue);
                                                        break;
                                                    case DataType.数值:
                                                        flag3 = decimal.Parse(value) < decimal.Parse(compareValue);
                                                        break;
                                                }
                                            }
                                            break;
                                        case "<=":
                                            {
                                                switch (dataType)
                                                {
                                                    case DataType.日期:
                                                        flag3 = DateTime.Parse(value) <= DateTime.Parse(compareValue);
                                                        break;
                                                    case DataType.数值:
                                                        flag3 = decimal.Parse(value) <= decimal.Parse(compareValue);
                                                        break;
                                                }
                                            }
                                            break;
                                        case "!=":
                                            {
                                                switch (dataType)
                                                {
                                                    case DataType.日期:
                                                        flag3 = DateTime.Parse(value) != DateTime.Parse(compareValue);
                                                        break;
                                                    case DataType.数值:
                                                        flag3 = decimal.Parse(value) != decimal.Parse(compareValue);
                                                        break;
                                                    case DataType.文本:
                                                        flag3 = value != compareValue;
                                                        break;
                                                }
                                            }
                                            break;
                                        case "包含":
                                            {
                                                flag3 = value.Contains(compareValue);
                                            }
                                            break;
                                    }

                                }
                                #endregion

                                if (logic == "")
                                {
                                    flag2 = flag3;
                                }
                                else
                                {
                                    if (logic == "and")
                                    {
                                        flag2 = flag2 && flag3;
                                    }
                                    else if (logic == "or")
                                    {
                                        flag2 = flag2 || flag3;
                                    }
                                }

                                logic = field.Element("Logic").Value;
                            }
                            #endregion

                            flag = flag && flag2;
                           
                        }

                    }

                    if (flag)
                    {
                        nodeIDs.Add(info.ToNodeID);
                    }

                }
            }

            return nodeIDs;
        }

        

        private bool Contains(IEnumerable<int> src, IEnumerable<int> dest)
        {
            bool flag = false;
            foreach (int i in dest)
            {
                if (src.Contains(i))
                {
                    flag = true;
                    break;
                }
            }
            return flag;
        }

        //protected void btnOK_Click(object sender, EventArgs e)
        //{
        //    string script = "var doc = top.document.getElementById('frameMain').contentWindow.document;" +
        //                    "doc.getElementById('" + hidSendID + "').value='" + hidSend.Value + "';" +
        //                    "doc.getElementById('" + hidAddSignID + "').value='" + hidAddSign.Value.Replace("-", "") + "';" +
        //                    "doc.getElementById('" + hidPassRoundID + "').value='" + hidPassRound.Value.Replace("-", "") + "';" +
        //                    "doc.getElementById('" + hidNextNodeID + "').value='" + lstNode.SelectedValue + "';" +
        //                    "top.delDivFrm();" +
        //                    "doc.getElementById('" + btnTransferID + "').click();";

        //    JSUtil.ResponseJS(script);

        //}
    }
}
